<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="utf-8" />
  <meta name="description" content="记录学习生活的点点滴滴" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <title>
    springMVC常用注解标签 |  Mysterious Blog
  </title>
  <meta name="generator" content="hexo-theme-ayer">
  <link rel="shortcut icon" href="/favicon.ico" />
<link rel="stylesheet" href="/dist/main.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css">
<link rel="stylesheet" href="/css/custom.css">
<script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>
<link rel="alternate" href="/atom.xml" title="Mysterious Blog" type="application/atom+xml">
</head>
</html>
<body>
  <div id="app">
    <main class="content on">
      <section class="outer">
  <article
  id="post-springMVC常用注解"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    <header class="article-header">
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  springMVC常用注解标签
</h1>
    </header>
    <div class="article-meta">
      <a href="/2021/02/14/springMVC%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3/" class="article-date">
  <time datetime="2021-02-14T12:39:43.000Z" itemprop="datePublished">2021-02-14</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E5%AD%A6%E4%B9%A0/">学习</a>
  </div>
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> Word count:</span>
            <span class="post-count">6.4k</span>
        </span>
    </span>
    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> Reading time≈</span>
            <span class="post-count">25 min</span>
        </span>
    </span>
</div>
    </div>
    <div class="tocbot"></div>
    <div class="article-entry" itemprop="articleBody">
  <h1 id="springmvc常用注解标签详解-https-www-cnblogs-com-leskang-p-5445698-html"><a href="#springmvc常用注解标签详解-https-www-cnblogs-com-leskang-p-5445698-html" class="headerlink" title="springmvc常用注解标签详解](https://www.cnblogs.com/leskang/p/5445698.html)"></a>springmvc常用注解标签详解](<a href="https://www.cnblogs.com/leskang/p/5445698.html" target="_blank" rel="noopener">https://www.cnblogs.com/leskang/p/5445698.html</a>)</h1><h2 id="1-Controller"><a href="#1-Controller" class="headerlink" title="1.@Controller"></a>1.@Controller</h2><p>在SpringMVC 中，控制器Controller 负责处理由DispatcherServlet 分发的请求，它把用户请求的数据经过业务处理层处理之后封装成一个Model ，然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法，你无需继承特定的类或实现特定的接口，只需使用@Controller 标记一个类是Controller ，然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射，这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象，它们可以通过Controller 的方法参数灵活的获取到。</p>
<p>@Controller 用于标记在一个类上，使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法，并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类，而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是SpringMVC 的一个控制器类，因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢？这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式：</p>
<p>　　（1）在SpringMVC 的配置文件中定义MyController 的bean 对象。</p>
<p>　　（2）在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--方式一--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">"com.host.app.web.controller.MyController"</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!--方式二--&gt;</span></span><br><span class="line"><span class="tag">&lt; <span class="attr">context:component-scan</span> <span class="attr">base-package</span> = <span class="string">"com.host.app.web"</span> /&gt;</span>//路径写到controller的上一层(扫描包详解见下面浅析)</span><br></pre></td></tr></table></figure>
<a id="more"></a>
<h2 id="2-RequestMapping"><a href="#2-RequestMapping" class="headerlink" title="2.@RequestMapping"></a>2.@RequestMapping</h2><p>RequestMapping是一个用来处理请求地址映射的注解，可用于类或方法上。用于类上，表示类中的所有响应请求的方法都是以该地址作为父路径。</p>
<p>RequestMapping注解有六个属性，下面我们把她分成三类进行说明（下面有相应示例）。</p>
<p><strong>1. value， method；</strong></p>
<p>value：   指定请求的实际地址，指定的地址可以是URI Template 模式（后面将会说明）；</p>
<p>method： 指定请求的method类型， GET.POST.PUT.DELETE等；</p>
<p><strong>2.consumes，produces</strong></p>
<p>consumes： 指定处理请求的提交内容类型（Content-Type），例如application/json, text/html;</p>
<p>produces:  指定返回的内容类型，仅当request请求头中的(Accept)类型中包含该指定类型才返回；</p>
<p><strong>3.params，headers</strong></p>
<p>params： 指定request中必须包含某些参数值是，才让该方法处理。</p>
<p>headers： 指定request中必须包含某些指定的header值，才能让该方法处理请求。</p>
<h2 id="3-Resource和-Autowired"><a href="#3-Resource和-Autowired" class="headerlink" title="3.@Resource和@Autowired"></a>3.@Resource和@Autowired</h2><p>@Resource和@Autowired都是做bean的注入时使用，其实@Resource并不是Spring的注解，它的包是javax.annotation.Resource，需要导入，但是Spring支持该注解的注入。</p>
<p><strong>1.共同点</strong></p>
<p>两者都可以写在字段和setter方法上。两者如果都写在字段上，那么就不需要再写setter方法。</p>
<p><strong>2.不同点</strong></p>
<p>（1）@Autowired</p>
<p>@Autowired为Spring提供的注解，需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestServiceImpl</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 下面两种@Autowired只要使用一种即可</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserDao userDao; <span class="comment">// 用于字段上</span></span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUserDao</span><span class="params">(UserDao userDao)</span> </span>&#123; <span class="comment">// 用于属性的方法上</span></span><br><span class="line">        <span class="keyword">this</span>.userDao = userDao;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>@Autowired注解是按照类型（byType）装配依赖对象，默认情况下它要求依赖对象必须存在，如果允许null值，可以设置它的required属性为false。如果我们想使用按照名称（byName）来装配，可以结合@Qualifier注解一起使用。如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestServiceImpl</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="meta">@Qualifier</span>(<span class="string">"userDao"</span>)</span><br><span class="line">    <span class="keyword">private</span> UserDao userDao; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>（2）@Resource</p>
<p>@Resource默认按照ByName自动注入，由J2EE提供，需要导入包javax.annotation.Resource。@Resource有两个重要的属性：name和type，而Spring将@Resource注解的name属性解析为bean的名字，而type属性则解析为bean的类型。所以，如果使用name属性，则使用byName的自动注入策略，而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性，这时将通过反射机制使用byName自动注入策略。</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestServiceImpl</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 下面两种@Resource只要使用一种即可</span></span><br><span class="line">    <span class="meta">@Resource</span>(name=<span class="string">"userDao"</span>)</span><br><span class="line">    <span class="keyword">private</span> UserDao userDao; <span class="comment">// 用于字段上</span></span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Resource</span>(name=<span class="string">"userDao"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUserDao</span><span class="params">(UserDao userDao)</span> </span>&#123; <span class="comment">// 用于属性的setter方法上</span></span><br><span class="line">        <span class="keyword">this</span>.userDao = userDao;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>注：最好是将@Resource放在setter方法上，因为这样更符合面向对象的思想，通过set.get去操作属性，而不是直接去操作属性。</p>
<p>@Resource装配顺序：</p>
<p>①如果同时指定了name和type，则从Spring上下文中找到唯一匹配的bean进行装配，找不到则抛出异常。</p>
<p>②如果指定了name，则从上下文中查找名称（id）匹配的bean进行装配，找不到则抛出异常。</p>
<p>③如果指定了type，则从上下文中找到类似匹配的唯一bean进行装配，找不到或是找到多个，都会抛出异常。</p>
<p>④如果既没有指定name，又没有指定type，则自动按照byName方式进行装配；如果没有匹配，则回退为一个原始类型进行匹配，如果匹配则自动装配。</p>
<p>@Resource的作用相当于@Autowired，只不过@Autowired按照byType自动注入。</p>
<h2 id="4-ModelAttribute和-SessionAttributes"><a href="#4-ModelAttribute和-SessionAttributes" class="headerlink" title="4.@ModelAttribute和 @SessionAttributes"></a>4.@ModelAttribute和 @SessionAttributes</h2><p>代表的是：该Controller的所有方法在调用前，先执行此@ModelAttribute方法，可用于注解和方法参数中，可以把这个@ModelAttribute特性，应用在BaseController当中，所有的Controller继承BaseController，即可实现在调用Controller时，先执行@ModelAttribute方法。</p>
<p> @SessionAttributes即将值放到session作用域中，写在class上面。</p>
<p>具体示例参见下面：使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据</p>
<h2 id="5-PathVariable"><a href="#5-PathVariable" class="headerlink" title="5.@PathVariable"></a>5.@PathVariable</h2><p>用于将请求URL中的模板变量映射到功能处理方法的参数上，即取出uri模板中的变量作为参数。如：</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestController</span> </span>&#123;  </span><br><span class="line">     <span class="meta">@RequestMapping</span>(value=<span class="string">"/user/&#123;userId&#125;/roles/&#123;roleId&#125;"</span>,method = RequestMethod.GET)  </span><br><span class="line">     <span class="function"><span class="keyword">public</span> String <span class="title">getLogin</span><span class="params">(@PathVariable(<span class="string">"userId"</span>)</span> String userId,  </span></span><br><span class="line"><span class="function">         @<span class="title">PathVariable</span><span class="params">(<span class="string">"roleId"</span>)</span> String roleId)</span>&#123;  </span><br><span class="line">         System.out.println(<span class="string">"User Id : "</span> + userId);  </span><br><span class="line">         System.out.println(<span class="string">"Role Id : "</span> + roleId);  </span><br><span class="line">         <span class="keyword">return</span> <span class="string">"hello"</span>;  </span><br><span class="line">     &#125;  </span><br><span class="line">     <span class="meta">@RequestMapping</span>(value=<span class="string">"/product/&#123;productId&#125;"</span>,method = RequestMethod.GET)  </span><br><span class="line">     <span class="function"><span class="keyword">public</span> String <span class="title">getProduct</span><span class="params">(@PathVariable(<span class="string">"productId"</span>)</span> String productId)</span>&#123;  </span><br><span class="line">           System.out.println(<span class="string">"Product Id : "</span> + productId);  </span><br><span class="line">           <span class="keyword">return</span> <span class="string">"hello"</span>;  </span><br><span class="line">     &#125;  </span><br><span class="line">     <span class="meta">@RequestMapping</span>(value=<span class="string">"/javabeat/&#123;regexp1:[a-z-]+&#125;"</span>,  </span><br><span class="line">           method = RequestMethod.GET)  </span><br><span class="line">     <span class="function"><span class="keyword">public</span> String <span class="title">getRegExp</span><span class="params">(@PathVariable(<span class="string">"regexp1"</span>)</span> String regexp1)</span>&#123;  </span><br><span class="line">           System.out.println(<span class="string">"URI Part 1 : "</span> + regexp1);  </span><br><span class="line">           <span class="keyword">return</span> <span class="string">"hello"</span>;  </span><br><span class="line">     &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h2 id="6-requestParam"><a href="#6-requestParam" class="headerlink" title="6.@requestParam"></a>6.@requestParam</h2><p>@requestParam主要用于在SpringMVC后台控制层获取参数，类似一种是request.getParameter(“name”)，它有三个常用参数：defaultValue = “0”, required = false, value = “isApp”；defaultValue 表示设置默认值，required 铜过boolean设置是否是必须要传入的参数，value 值表示接受的传入的参数类型。</p>
<h2 id="7-ResponseBody"><a href="#7-ResponseBody" class="headerlink" title="7.@ResponseBody"></a>7.@ResponseBody</h2><p>作用： 该注解用于将Controller的方法返回的对象，通过适当的HttpMessageConverter转换为指定格式后，写入到Response对象的body数据区。</p>
<p>使用时机：返回的数据不是html标签的页面，而是其他某种格式的数据时（如json.xml等）使用；</p>
<h2 id="8-Component"><a href="#8-Component" class="headerlink" title="8.@Component"></a>8.<strong>@Component</strong></h2><p>相当于通用的注解，当不知道一些类归到哪个层时使用，但是不建议。</p>
<h2 id="9-Repository"><a href="#9-Repository" class="headerlink" title="9.@Repository"></a>9.@Repository</h2><p>用于注解dao层，在daoImpl类上面注解。</p>
<h2 id="注："><a href="#注：" class="headerlink" title="注："></a>注：</h2><h4 id="1-使用-RequestMapping-来映射-Request-请求与处理器"><a href="#1-使用-RequestMapping-来映射-Request-请求与处理器" class="headerlink" title="1.使用 @RequestMapping 来映射 Request 请求与处理器"></a>1.使用 @RequestMapping 来映射 Request 请求与处理器</h4><p>方式一.通过常见的类路径和方法路径结合访问controller方法</p>
<p>方式二.使用uri模板</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping</span> ( <span class="string">"/test/&#123;variable1&#125;"</span> )</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyController</span> </span>&#123;</span><br><span class="line">    <span class="meta">@RequestMapping</span> ( <span class="string">"/showView/&#123;variable2&#125;"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ModelAndView <span class="title">showView</span><span class="params">( @PathVariable String variable1, @PathVariable ( <span class="string">"variable2"</span> )</span> <span class="keyword">int</span> variable2) </span>&#123;</span><br><span class="line">       ModelAndView modelAndView = <span class="keyword">new</span> ModelAndView();</span><br><span class="line">       modelAndView.setViewName( <span class="string">"viewName"</span> );</span><br><span class="line">       modelAndView.addObject( <span class="string">" 需要放到 model 中的属性名称 "</span> , <span class="string">" 对应的属性值，它是一个对象 "</span> );</span><br><span class="line">       <span class="keyword">return</span> modelAndView;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>URI 模板就是在URI 中给定一个变量，然后在映射的时候动态的给该变量赋值。如URI 模板<a href="http://localhost/app/{variable1}/index.html" target="_blank" rel="noopener">http://localhost/app/{variable1}/index.html</a> ，这个模板里面包含一个变量variable1 ，那么当我们请求<a href="http://localhost/app/hello/index.html" target="_blank" rel="noopener">http://localhost/app/hello/index.html</a> 的时候，该URL 就跟模板相匹配，只是把模板中的variable1 用hello 来取代。这个变量在SpringMVC 中是使用@PathVariable 来标记的。在SpringMVC 中，我们可以使用@PathVariable 来标记一个Controller 的处理方法参数，表示该参数的值将使用URI 模板中对应的变量的值来赋值。</p>
<p>代码中我们定义了两个URI 变量，一个是控制器类上的variable1 ，一个是showView 方法上的variable2 ，然后在showView 方法的参数里面使用<strong>@PathVariable</strong> 标记使用了这两个变量。所以当我们使用/test/hello/showView/2.do 来请求的时候就可以访问到MyController 的showView 方法，这个时候variable1 就被赋予值hello ，variable2 就被赋予值2 ，然后我们在showView 方法参数里面标注了参数variable1 和variable2 是来自访问路径的path 变量，这样方法参数variable1 和variable2 就被分别赋予hello 和2 。方法参数variable1 是定义为String 类型，variable2 是定义为int 类型，像这种简单类型在进行赋值的时候Spring 是会帮我们自动转换的。</p>
<p>  在上面的代码中我们可以看到在标记variable1 为path 变量的时候我们使用的是@PathVariable ，而在标记variable2 的时候使用的是@PathVariable(“variable2”) 。这两者有什么区别呢？第一种情况就默认去URI 模板中找跟参数名相同的变量，但是这种情况只有在使用debug 模式进行编译的时候才可以，而第二种情况是明确规定使用的就是URI 模板中的variable2 变量。当不是使用debug 模式进行编译，或者是所需要使用的变量名跟参数名不相同的时候，就要使用第二种方式明确指出使用的是URI 模板中的哪个变量。</p>
<p> 除了在请求路径中使用URI 模板，定义变量之外，<strong>@RequestMapping 中还支持通配符“* ”</strong>。如下面的代码我就可以使用/myTest/whatever/wildcard.do 访问到Controller 的testWildcard 方法。如：</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping</span> ( <span class="string">"/myTest"</span> )</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyController</span> </span>&#123;</span><br><span class="line">    <span class="meta">@RequestMapping</span> ( <span class="string">"*/wildcard"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">testWildcard</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"wildcard------------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="string">"wildcard"</span> ;</span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>当@RequestParam中没有指定参数名称时，Spring 在代码是debug 编译的情况下会默认取更方法参数同名的参数，如果不是debug 编译的就会报错。</p>
<h4 id="2-使用-RequestMapping-的一些高级用法"><a href="#2-使用-RequestMapping-的一些高级用法" class="headerlink" title="2.使用 @RequestMapping 的一些高级用法"></a>2.使用 @RequestMapping 的一些高级用法</h4><p>（1）params属性</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping</span> (value= <span class="string">"testParams"</span> , params=&#123; <span class="string">"param1=value1"</span> , <span class="string">"param2"</span> , <span class="string">"!param3"</span> &#125;)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">testParams</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"test Params..........."</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="string">"testParams"</span> ;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>用@RequestMapping 的params 属性指定了三个参数，这些参数都是针对请求参数而言的，它们分别表示参数param1 的值必须等于value1 ，参数param2 必须存在，值无所谓，参数param3 必须不存在，只有当请求/testParams.do 并且满足指定的三个参数条件的时候才能访问到该方法。所以当请求/testParams.do?param1=value1&amp;param2=value2 的时候能够正确访问到该testParams 方法，当请求/testParams.do?param1=value1&amp;param2=value2&amp;param3=value3 的时候就不能够正常的访问到该方法，因为在@RequestMapping 的params 参数里面指定了参数param3 是不能存在的。</p>
<p>（2）method属性</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping</span> (value= <span class="string">"testMethod"</span> , method=&#123;RequestMethod. GET , RequestMethod. DELETE &#125;)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">testMethod</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="string">"method"</span> ;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>在上面的代码中就使用method 参数限制了以GET 或DELETE 方法请求/testMethod 的时候才能访问到该Controller 的testMethod 方法。</p>
<p>（3）headers属性</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping</span> (value= <span class="string">"testHeaders"</span> , headers=&#123; <span class="string">"host=localhost"</span> , <span class="string">"Accept"</span> &#125;)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">testHeaders</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="string">"headers"</span> ;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>headers 属性的用法和功能与params 属性相似。在上面的代码中当请求/testHeaders.do 的时候只有当请求头包含Accept 信息，且请求的host 为localhost 的时候才能正确的访问到testHeaders 方法。</p>
<h3 id="3-RequestMapping-标记的处理器方法支持的方法参数和返回类型"><a href="#3-RequestMapping-标记的处理器方法支持的方法参数和返回类型" class="headerlink" title="3. @RequestMapping 标记的处理器方法支持的方法参数和返回类型"></a>3. @RequestMapping 标记的处理器方法支持的方法参数和返回类型</h3><h4 id="1-支持的方法参数类型"><a href="#1-支持的方法参数类型" class="headerlink" title="1. 支持的方法参数类型"></a>1. 支持的方法参数类型</h4><p>​     <strong>（1 ）HttpServlet 对象，主要包括HttpServletRequest .HttpServletResponse 和HttpSession 对象。</strong> 这些参数Spring 在调用处理器方法的时候会自动给它们赋值，所以当在处理器方法中需要使用到这些对象的时候，可以直接在方法上给定一个方法参数的申明，然后在方法体里面直接用就可以了。但是有一点需要注意的是在使用HttpSession 对象的时候，如果此时HttpSession 对象还没有建立起来的话就会有问题。</p>
<p>  <strong>（2 ）Spring 自己的WebRequest 对象。</strong> 使用该对象可以访问到存放在HttpServletRequest 和HttpSession 中的属性值。</p>
<p>  <strong>（3 ）InputStream .OutputStream .Reader 和Writer 。</strong> InputStream 和Reader 是针对HttpServletRequest 而言的，可以从里面取数据；OutputStream 和Writer 是针对HttpServletResponse 而言的，可以往里面写数据。</p>
<p>  <strong>（4 ）使用@PathVariable .@RequestParam .@CookieValue 和@RequestHeader 标记的参数。</strong></p>
<p>  <strong>（5 ）使用@ModelAttribute 标记的参数。</strong></p>
<p>  <strong>（6 ）java.util.Map .Spring 封装的Model 和ModelMap 。</strong> 这些都可以用来封装模型数据，用来给视图做展示。</p>
<p>  <strong>（7 ）实体类。</strong> 可以用来接收上传的参数。</p>
<p>  <strong>（8 ）Spring 封装的MultipartFile 。</strong> 用来接收上传文件的。</p>
<p>  <strong>（9 ）Spring 封装的Errors 和BindingResult 对象。</strong> 这两个对象参数必须紧接在需要验证的实体对象参数之后，它里面包含了实体对象的验证结果。</p>
<h4 id="2-支持的返回类型"><a href="#2-支持的返回类型" class="headerlink" title="2. 支持的返回类型"></a>2. 支持的返回类型</h4><p>  （1 ）一个包含模型和视图的ModelAndView 对象。</p>
<p>  （2 ）一个模型对象，这主要包括Spring 封装好的Model 和ModelMap ，以及java.util.Map ，当没有视图返回的时候视图名称将由RequestToViewNameTranslator 来决定。</p>
<p>  （3 ）一个View 对象。这个时候如果在渲染视图的过程中模型的话就可以给处理器方法定义一个模型参数，然后在方法体里面往模型中添加值。</p>
<p>  （4 ）一个String 字符串。这往往代表的是一个视图名称。这个时候如果需要在渲染视图的过程中需要模型的话就可以给处理器方法一个模型参数，然后在方法体里面往模型中添加值就可以了。</p>
<p>  （5 ）返回值是void 。这种情况一般是我们直接把返回结果写到HttpServletResponse 中了，如果没有写的话，那么Spring 将会利用RequestToViewNameTranslator 来返回一个对应的视图名称。如果视图中需要模型的话，处理方法与返回字符串的情况相同。</p>
<p>  （6 ）如果处理器方法被注解@ResponseBody 标记的话，那么处理器方法的任何返回类型都会通过HttpMessageConverters 转换之后写到HttpServletResponse 中，而不会像上面的那些情况一样当做视图或者模型来处理。</p>
<p>  （7 ）除以上几种情况之外的其他任何返回类型都会被当做模型中的一个属性来处理，而返回的视图还是由RequestToViewNameTranslator 来决定，添加到模型中的属性名称可以在该方法上用@ModelAttribute(“attributeName”) 来定义，否则将使用返回类型的类名称的首字母小写形式来表示。使用@ModelAttribute 标记的方法会在@RequestMapping 标记的方法执行之前执行。</p>
<h3 id="4-使用-ModelAttribute-和-SessionAttributes-传递和保存数据"><a href="#4-使用-ModelAttribute-和-SessionAttributes-传递和保存数据" class="headerlink" title="4.使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据"></a>4.使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据</h3><p>SpringMVC 支持使用 @<strong>ModelAttribute</strong> 和 @<strong>SessionAttributes</strong> 在不同的模型（model）和控制器之间共享数据。 <strong>@ModelAttribute</strong> 主要有两种使用方式，一种是标注在方法上，一种是标注在 Controller 方法参数上。</p>
<p>当 @<strong>ModelAttribute</strong> 标记在方法上的时候，该方法将在处理器方法执行之前执行，然后把返回的对象存放在 session 或模型属性中，属性名称可以使用 @<strong>ModelAttribute</strong>(“attributeName”) 在标记方法的时候指定，若未指定，则使用返回类型的类名称（首字母小写）作为属性名称。关于 @ModelAttribute 标记在方法上时对应的属性是存放在 session 中还是存放在模型中，我们来做一个实验，看下面一段代码。</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping</span> ( <span class="string">"/myTest"</span> )</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ModelAttribute</span> ( <span class="string">"hello"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getModel</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"-------------Hello---------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="string">"world"</span> ;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ModelAttribute</span> ( <span class="string">"intValue"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getInteger</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"-------------intValue---------------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping</span> ( <span class="string">"sayHello"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">sayHello</span><span class="params">( @ModelAttribute ( <span class="string">"hello"</span> )</span> String hello, @<span class="title">ModelAttribute</span> <span class="params">( <span class="string">"intValue"</span> )</span> <span class="keyword">int</span> num, @<span class="title">ModelAttribute</span> <span class="params">( <span class="string">"user2"</span> )</span> User user, Writer writer, HttpSession session) <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">       writer.write( <span class="string">"Hello "</span> + hello + <span class="string">" , Hello "</span> + user.getUsername() + num);</span><br><span class="line">       writer.write( <span class="string">"\r"</span> );</span><br><span class="line">       Enumeration enume = session.getAttributeNames();</span><br><span class="line">       <span class="keyword">while</span> (enume.hasMoreElements())</span><br><span class="line">           writer.write(enume.nextElement() + <span class="string">"\r"</span> );</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ModelAttribute</span> ( <span class="string">"user2"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> User <span class="title">getUser</span><span class="params">()</span></span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"---------getUser-------------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">new</span> User(<span class="number">3</span>, <span class="string">"user2"</span> );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>当我们请求 /myTest/sayHello.do 的时候使用 @ModelAttribute 标记的方法会先执行，然后把它们返回的对象存放到模型中。最终访问到 sayHello 方法的时候，使用 @ModelAttribute 标记的方法参数都能被正确的注入值。执行结果如下所示：</p>
<p> <em>Hello world,Hello user210</em></p>
<p>​    由执行结果我们可以看出来，此时 session 中没有包含任何属性，也就是说上面的那些对象都是存放在模型属性中，而不是存放在 session 属性中。那要如何才能存放在 session 属性中呢？这个时候我们先引入一个新的概念 @SessionAttributes ，它的用法会在讲完 @ModelAttribute 之后介绍，这里我们就先拿来用一下。我们在 MyController 类上加上 @SessionAttributes 属性标记哪些是需要存放到 session 中的。看下面的代码：</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping</span> ( <span class="string">"/myTest"</span> )</span><br><span class="line"><span class="meta">@SessionAttributes</span> (value=&#123; <span class="string">"intValue"</span> , <span class="string">"stringValue"</span> &#125;, types=&#123;User. <span class="class"><span class="keyword">class</span> &#125;)</span></span><br><span class="line"><span class="class"><span class="title">public</span> <span class="title">class</span> <span class="title">MyController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ModelAttribute</span> ( <span class="string">"hello"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getModel</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"-------------Hello---------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="string">"world"</span> ;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ModelAttribute</span> ( <span class="string">"intValue"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getInteger</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"-------------intValue---------------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line">   </span><br><span class="line">    <span class="meta">@RequestMapping</span> ( <span class="string">"sayHello"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">sayHello</span><span class="params">(Map&lt;String, Object&gt; map, @ModelAttribute ( <span class="string">"hello"</span> )</span> String hello, @<span class="title">ModelAttribute</span> <span class="params">( <span class="string">"intValue"</span> )</span> <span class="keyword">int</span> num, @<span class="title">ModelAttribute</span> <span class="params">( <span class="string">"user2"</span> )</span> User user, Writer writer, HttpServletRequest request) <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">       map.put( <span class="string">"stringValue"</span> , <span class="string">"String"</span> );</span><br><span class="line">       writer.write( <span class="string">"Hello "</span> + hello + <span class="string">" , Hello "</span> + user.getUsername() + num);</span><br><span class="line">       writer.write( <span class="string">"\r"</span> );</span><br><span class="line">       HttpSession session = request.getSession();</span><br><span class="line">       Enumeration enume = session.getAttributeNames();</span><br><span class="line">       <span class="keyword">while</span> (enume.hasMoreElements())</span><br><span class="line">           writer.write(enume.nextElement() + <span class="string">"\r"</span> );</span><br><span class="line">       System. out .println(session);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ModelAttribute</span> ( <span class="string">"user2"</span> )</span><br><span class="line">    <span class="function"><span class="keyword">public</span> User <span class="title">getUser</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       System. out .println( <span class="string">"---------getUser-------------"</span> );</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">new</span> User(<span class="number">3</span>, <span class="string">"user2"</span> );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>在上面代码中我们指定了属性为 intValue 或 stringValue 或者类型为 User 的都会放到 Session中，利用上面的代码当我们访问 /myTest/sayHello.do 的时候，结果如下：</p>
<p> <em>Hello world,Hello user210</em></p>
<p>仍然没有打印出任何 session 属性，这是怎么回事呢？怎么定义了把模型中属性名为 intValue 的对象和类型为 User 的对象存到 session 中，而实际上没有加进去呢？难道我们错啦？我们当然没有错，只是在第一次访问 /myTest/sayHello.do 的时候 @SessionAttributes 定义了需要存放到 session 中的属性，而且这个模型中也有对应的属性，但是这个时候还没有加到 session 中，所以 session 中不会有任何属性，等处理器方法执行完成后 Spring 才会把模型中对应的属性添加到 session 中。所以当请求第二次的时候就会出现如下结果：</p>
<p> <em>Hello world,Hello user210</em></p>
<p><em>user2</em></p>
<p><em>intValue</em></p>
<p><em>stringValue</em></p>
<p>当 @ModelAttribute 标记在处理器方法参数上的时候，表示该参数的值将从模型或者 Session 中取对应名称的属性值，该名称可以通过 @ModelAttribute(“attributeName”) 来指定，若未指定，则使用参数类型的类名称（首字母小写）作为属性名称。</p>
<h3 id="5-PathVariable和-RequestParam的区别"><a href="#5-PathVariable和-RequestParam的区别" class="headerlink" title="5.@PathVariable和@RequestParam的区别"></a>5.@PathVariable和@RequestParam的区别</h3><p>请求路径上有个id的变量值，可以通过@PathVariable来获取 @RequestMapping(value = “/page/{id}”, method = RequestMethod.GET)<br>@RequestParam用来获得静态的URL请求入参   spring注解时action里用到。</p>
<h4 id="简介："><a href="#简介：" class="headerlink" title="简介："></a>简介：</h4><p>handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类：（主要讲解常用类型）</p>
<p>A.处理<strong>requet uri</strong> 部分（这里指uri template中variable，不含queryString部分）的注解：  @PathVariable;</p>
<p>B.处理<strong>request header</strong>部分的注解：  @RequestHeader, @CookieValue;</p>
<p>C.处理<strong>request body</strong>部分的注解：@RequestParam, @RequestBody;</p>
<p>D.处理<strong>attribute</strong>类型是注解： @SessionAttributes, @ModelAttribute;</p>
<h4 id="（1）-PathVariable"><a href="#（1）-PathVariable" class="headerlink" title="（1）.@PathVariable"></a>（1）.@PathVariable</h4><p>当使用@RequestMapping URI template 样式映射时， 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。</p>
<p>示例代码：</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span>  </span><br><span class="line"><span class="meta">@RequestMapping</span>(<span class="string">"/owners/&#123;ownerId&#125;"</span>)  </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RelativePathUriTemplateController</span> </span>&#123;  </span><br><span class="line">  </span><br><span class="line">  <span class="meta">@RequestMapping</span>(<span class="string">"/pets/&#123;petId&#125;"</span>)  </span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">findPet</span><span class="params">(@PathVariable String ownerId, @PathVariable String petId, Model model)</span> </span>&#123;      </span><br><span class="line">    <span class="comment">// implementation omitted   </span></span><br><span class="line">  &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>上面代码把URI template 中变量 ownerId的值和petId的值，绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致，需要在@PathVariable(“name”)指定uri template中的名称。</p>
<h4 id="（2）-RequestHeader-CookieValue"><a href="#（2）-RequestHeader-CookieValue" class="headerlink" title="（2）. @RequestHeader.@CookieValue"></a>（2）. @RequestHeader.@CookieValue</h4><p>@RequestHeader 注解，可以把Request请求header部分的值绑定到方法的参数上。</p>
<p>示例代码：</p>
<p>这是一个Request 的header部分：</p>
<ol>
<li><p>Host          localhost:8080 </p>
</li>
<li><p>Accept         text/html,application/xhtml+xml,application/xml;q=0.9 </p>
</li>
<li><p>Accept-Language     fr,en-gb;q=0.7,en;q=0.3 </p>
</li>
<li><p>Accept-Encoding     gzip,deflate </p>
</li>
<li><p>Accept-Charset     ISO-8859-1,utf-8;q=0.7,*;q=0.7 </p>
</li>
<li><p>Keep-Alive       300 </p>
</li>
<li><p>@RequestMapping(“/displayHeaderInfo.do”) </p>
</li>
<li><p><strong>public</strong> <strong>void</strong> displayHeaderInfo(@RequestHeader(“Accept-Encoding”) String encoding, </p>
</li>
<li><p>​               @RequestHeader(“Keep-Alive”) <strong>long</strong> keepAlive) { </p>
</li>
<li><p>} </p>
</li>
</ol>
<p>上面的代码，把request header部分的 Accept-Encoding的值，绑定到参数encoding上了， Keep-Alive header的值绑定到参数keepAlive上。</p>
<p>@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。</p>
<p>例如有如下Cookie值：</p>
<p>　　JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping</span>(<span class="string">"/displayHeaderInfo.do"</span>)  </span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">displayHeaderInfo</span><span class="params">(@CookieValue(<span class="string">"JSESSIONID"</span>)</span> String cookie)  </span>&#123;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>即把JSESSIONID的值绑定到参数cookie上。</p>
<h4 id="（3）-RequestParam-RequestBody"><a href="#（3）-RequestParam-RequestBody" class="headerlink" title="（3）.@RequestParam, @RequestBody"></a>（3）.@RequestParam, @RequestBody</h4><p>@RequestParam </p>
<p>A） 常用来处理简单类型的绑定，<strong>通过Request.getParameter() 获取的String可直接转换为简单类型的情况</strong>（ String–&gt; 简单类型的转换操作由ConversionService配置的转换器来完成）；因为使用request.getParameter()方式获取参数，所以可以处理<strong>get 方式中queryString的值</strong>，也可以处理<strong>post方式中 body data的值</strong>；</p>
<p>B）用来处理Content-Type: 为 <code>application/x-www-form-urlencoded</code>编码的内容，提交方式GET.POST；</p>
<p>C) 该注解有两个属性： value.required； value用来指定要传入值的id名称，required用来指示参数是否必须绑定；</p>
<p>示例代码：</p>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span>  </span><br><span class="line"><span class="meta">@RequestMapping</span>(<span class="string">"/pets"</span>)  </span><br><span class="line"><span class="meta">@SessionAttributes</span>(<span class="string">"pet"</span>)  </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EditPetForm</span> </span>&#123;  </span><br><span class="line">    <span class="meta">@RequestMapping</span>(method = RequestMethod.GET)  </span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">setupForm</span><span class="params">(@RequestParam(<span class="string">"petId"</span>)</span> <span class="keyword">int</span> petId, ModelMap model) </span>&#123;  </span><br><span class="line">       Pet pet = <span class="keyword">this</span>.clinic.loadPet(petId);  </span><br><span class="line">   model.addAttribute(<span class="string">"pet"</span>, pet);  </span><br><span class="line">   <span class="keyword">return</span> <span class="string">"petForm"</span>;  </span><br><span class="line">   &#125;&#125;</span><br></pre></td></tr></table></figure>
<p><a href="javascript:void(0);"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>@RequestBody</p>
<p>该注解常用来处理Content-Type: 不是<code>application/x-www-form-urlencoded</code>编码的内容，例如application/json, application/xml等；</p>
<p>它是通过使用HandlerAdapter 配置的<code>HttpMessageConverters</code>来解析post data body，然后绑定到相应的bean上的。</p>
<p>因为配置有FormHttpMessageConverter，所以也可以用来处理 <code>application/x-www-form-urlencoded</code>的内容，处理完的结果放在一个MultiValueMap&lt;String, String&gt;里，这种情况在某些特殊需求下使用，详情查看FormHttpMessageConverter api;</p>
<p>示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping</span>(value = <span class="string">"/something"</span>, method = RequestMethod.PUT)  </span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handle</span><span class="params">(@RequestBody String body, Writer writer)</span> <span class="keyword">throws</span> IOException </span>&#123;  </span><br><span class="line">  writer.write(body);  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="（4）-SessionAttributes-ModelAttribute"><a href="#（4）-SessionAttributes-ModelAttribute" class="headerlink" title="（4）.@SessionAttributes, @ModelAttribute"></a>（4）.@SessionAttributes, @ModelAttribute</h4><p>@SessionAttributes:</p>
<p>该注解用来绑定HttpSession中的attribute对象的值，便于在方法中的参数里使用。</p>
<p>该注解有value.types两个属性，可以通过名字和类型指定要使用的attribute 对象；</p>
<p>示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span>  </span><br><span class="line"><span class="meta">@RequestMapping</span>(<span class="string">"/editPet.do"</span>)  </span><br><span class="line"><span class="meta">@SessionAttributes</span>(<span class="string">"pet"</span>)  </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EditPetForm</span> </span>&#123;  </span><br><span class="line">    <span class="comment">// ...   </span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>@ModelAttribute</p>
<p>该注解有两个用法，一个是用于方法上，一个是用于参数上；</p>
<p>用于方法上时： 通常用来在处理@RequestMapping之前，为请求绑定需要从后台查询的model；</p>
<p>用于参数上时： 用来通过名称对应，把相应名称的值绑定到注解的参数bean上；要绑定的值来源于：</p>
<p>A） @SessionAttributes 启用的attribute 对象上；</p>
<p>B） @ModelAttribute 用于方法上时指定的model对象；</p>
<p>C） 上述两种情况都没有时，new一个需要绑定的bean对象，然后把request中按名称对应的方式把值绑定到bean中。</p>
<p>用到方法上@ModelAttribute的示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ModelAttribute</span>  </span><br><span class="line"><span class="function"><span class="keyword">public</span> Account <span class="title">addAccount</span><span class="params">(@RequestParam String number)</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">return</span> accountManager.findAccount(number);  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这种方式实际的效果就是在调用@RequestMapping的方法之前，为request对象的model里put（“account”， Account）。</p>
<p>用在参数上的@ModelAttribute示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping</span>(value=<span class="string">"/owners/&#123;ownerId&#125;/pets/&#123;petId&#125;/edit"</span>, method = RequestMethod.POST)  </span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">processSubmit</span><span class="params">(@ModelAttribute Pet pet)</span> </span>&#123;  </span><br><span class="line">     </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>首先查询 @SessionAttributes有无绑定的Pet对象，若没有则查询@ModelAttribute方法层面上是否绑定了Pet对象，若没有则将URI template中的值按对应的名称绑定到Pet对象的各属性上。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">6.<span class="tag">&lt; <span class="attr">context:component-scan</span> <span class="attr">base-package</span> = <span class="string">""</span> /&gt;</span>浅析</span><br></pre></td></tr></table></figure>
<p>component-scan 默认扫描的注解类型是 @Component，不过，在 @Component 语义基础上细化后的 @Repository, @Service 和 @Controller 也同样可以获得 component-scan 的青睐</p>
<p>有了<a href="context:component-scan">context:component-scan</a>，另一个<a href="context:annotation-config/">context:annotation-config/</a>标签根本可以移除掉，因为已经被包含进去了</p>
<p>另外<a href="context:annotation-config/">context:annotation-config/</a>还提供了两个子标签</p>
<p>\1.    <a href="context:include-filter">context:include-filter</a> //指定扫描的路径</p>
<p>\2.    <a href="context:exclude-filter">context:exclude-filter</a> //排除扫描的路径</p>
<p><a href="context:component-scan">context:component-scan</a>有一个use-default-filters属性，属性默认为true,表示会扫描指定包下的全部的标有@Component的类，并注册成bean.也就是@Component的子注解@Service,@Reposity等。</p>
<p>这种扫描的粒度有点太大，如果你只想扫描指定包下面的Controller或其他内容则设置use-default-filters属性为false，表示不再按照scan指定的包扫描，而是按照<a href="context:include-filter">context:include-filter</a>指定的包扫描，示例：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"com.tan"</span> <span class="attr">use-default-filters</span>=<span class="string">"false"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">context:include-filter</span> <span class="attr">type</span>=<span class="string">"regex"</span> <span class="attr">expression</span>=<span class="string">"com.tan.*"</span>/&gt;</span>//注意后面要写.*</span><br><span class="line"><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">当没有设置use-default-filters属性或者属性为true时，表示基于base-packge包下指定扫描的具体路径</span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"com.tan"</span> &gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">context:include-filter</span> <span class="attr">type</span>=<span class="string">"regex"</span> <span class="attr">expression</span>=<span class="string">".controller.*"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">context:include-filter</span> <span class="attr">type</span>=<span class="string">"regex"</span> <span class="attr">expression</span>=<span class="string">".service.*"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">context:include-filter</span> <span class="attr">type</span>=<span class="string">"regex"</span> <span class="attr">expression</span>=<span class="string">".dao.*"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">效果相当于：</span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"com.tan"</span> &gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">context:exclude-filter</span> <span class="attr">type</span>=<span class="string">"regex"</span> <span class="attr">expression</span>=<span class="string">".model.*"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">注意：本人尝试时无论哪种情况&lt;context:include-filter&gt;和&lt;context:exclude-filter&gt;都不能同时存在</span><br></pre></td></tr></table></figure> 
      <!-- reward -->
      <div id="reword-out">
        <div id="reward-btn">
          Donate
        </div>
      </div>
    </div>
    <!-- copyright -->
    <div class="declare">
      <ul class="post-copyright">
        <li>
          <i class="ri-copyright-line"></i>
          <strong>Copyright： </strong>
          Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
        </li>
      </ul>
    </div>
    <footer class="article-footer">
<div class="share-btn">
      <span class="share-sns share-outer">
        <i class="ri-share-forward-line"></i>
        分享
      </span>
      <div class="share-wrap">
        <i class="arrow"></i>
        <div class="share-icons">
          <a class="weibo share-sns" href="javascript:;" data-type="weibo">
            <i class="ri-weibo-fill"></i>
          </a>
          <a class="weixin share-sns wxFab" href="javascript:;" data-type="weixin">
            <i class="ri-wechat-fill"></i>
          </a>
          <a class="qq share-sns" href="javascript:;" data-type="qq">
            <i class="ri-qq-fill"></i>
          </a>
          <a class="douban share-sns" href="javascript:;" data-type="douban">
            <i class="ri-douban-line"></i>
          </a>
          <!-- <a class="qzone share-sns" href="javascript:;" data-type="qzone">
            <i class="icon icon-qzone"></i>
          </a> -->
          <a class="facebook share-sns" href="javascript:;" data-type="facebook">
            <i class="ri-facebook-circle-fill"></i>
          </a>
          <a class="twitter share-sns" href="javascript:;" data-type="twitter">
            <i class="ri-twitter-fill"></i>
          </a>
          <a class="google share-sns" href="javascript:;" data-type="google">
            <i class="ri-google-fill"></i>
          </a>
        </div>
      </div>
</div>
<div class="wx-share-modal">
    <a class="modal-close" href="javascript:;"><i class="ri-close-circle-line"></i></a>
    <p>扫一扫，分享到微信</p>
    <div class="wx-qrcode">
      <img src="//api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://www.kangxh.ga/2021/02/14/springMVC%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3/" alt="微信分享二维码">
    </div>
</div>
<div id="share-mask"></div>  
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/spring/" rel="tag">spring</a></li></ul>
    </footer>
  </div>
  <nav class="article-nav">
      <a href="/2021/02/14/Python%E5%AD%A6%E4%B9%A0%E5%87%86%E5%A4%87%EF%BC%9AAnaconda%E5%92%8CPycharm%E7%9A%84%E5%AE%89%E8%A3%85%E5%8F%8A%E7%8E%AF%E5%A2%83%E5%88%9B%E5%BB%BA/" class="article-nav-link">
        <strong class="article-nav-caption">上一篇</strong>
        <div class="article-nav-title">
            Python学习准备：Anaconda和Pycharm的安装及环境创建
        </div>
      </a>
      <a href="/2021/02/14/vscode%E5%BF%AB%E6%8D%B7%E9%94%AE/" class="article-nav-link">
        <strong class="article-nav-caption">下一篇</strong>
        <div class="article-nav-title">VSCode的快捷键</div>
      </a>
  </nav>
<!-- valine评论 -->
<div id="vcomments-box">
  <div id="vcomments"></div>
</div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js"></script>
<script>
  new Valine({
    el: "#vcomments",
    app_id: "lC7lsHHM0HSqJA3yOqH70saX-gzGzoHsz",
    app_key: "mCkqEEjUbhRIHjXJ7mtxTgfA",
    path: window.location.pathname,
    avatar: "monsterid",
    placeholder: "ヾﾉ≧∀≦)o来啊，快活啊!",
    recordIP: true,
  });
  const infoEle = document.querySelector("#vcomments .info");
  if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0) {
    infoEle.childNodes.forEach(function (item) {
      item.parentNode.removeChild(item);
    });
  }
</script>
<style>
  #vcomments-box {
    padding: 5px 30px;
  }
  @media screen and (max-width: 800px) {
    #vcomments-box {
      padding: 5px 0px;
    }
  }
  #vcomments-box #vcomments {
    background-color: #fff;
  }
  .v .vlist .vcard .vh {
    padding-right: 20px;
  }
  .v .vlist .vcard {
    padding-left: 10px;
  }
</style>
</article>
</section>
      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2020-2021
        <i class="ri-heart-fill heart_icon"></i> Mystery
      </li>
    </ul>
    <ul>
      <li>
        Powered by <a href="https://hexo.io" target="_blank">Hexo</a>
        <span class="division">|</span>
        Theme - <a href="https://github.com/Shen-Yu/hexo-theme-ayer" target="_blank">Ayer</a>
      </li>
    </ul>
    <ul>
      <li>
        <span>
  <span><i class="ri-user-3-fill"></i>Visitors:<span id="busuanzi_value_site_uv"></span></s>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>Views:<span id="busuanzi_value_page_pv"></span></span>
</span>
      </li>
    </ul>
    <ul>
    </ul>
    <ul>
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        <script type="text/javascript" src='https://s9.cnzz.com/z_stat.php?id=1278069914&amp;web_id=1278069914'></script>
      </li>
    </ul>
  </div>
</footer>
      <div class="float_btns">
        <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>
<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>
      </div>
    </main>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  <div class="logo">
    <a href="/"><img src="/images/ayer-side.svg" alt="Mysterious Blog"></a>
  </div>
  <ul class="nav nav-main">
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    <li class="nav-item">
      <a class="nav-item-link" href="/friends">友链</a>
    </li>
    <li class="nav-item">
      <a class="nav-item-link" href="/player">影音</a>
    </li>
    <li class="nav-item">
      <a class="nav-item-link" href="/about">关于我</a>
    </li>
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      <a class="nav-item-link nav-item-search"  title="Search">
        <i class="ri-search-line"></i>
      </a>
      <a class="nav-item-link" target="_blank" href="/atom.xml" title="RSS Feed">
        <i class="ri-rss-line"></i>
      </a>
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <script>
      if (window.matchMedia("(max-width: 768px)").matches) {
        document.querySelector('.content').classList.remove('on');
        document.querySelector('.sidebar').classList.remove('on');
      }
    </script>
    <div id="mask"></div>
<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>请我喝杯咖啡吧~</p>
  <div class="reward-box">
    <div class="reward-item">
      <img class="reward-img" src="https://gitee.com/LYmystery/PicGo/raw/master/img/alipay.jpg">
      <span class="reward-type">支付宝</span>
    </div>
    <div class="reward-item">
      <img class="reward-img" src="https://gitee.com/LYmystery/PicGo/raw/master/img/wechat.jpg">
      <span class="reward-type">微信</span>
    </div>
  </div>
</div>
<script src="/js/jquery-2.0.3.min.js"></script>
<script src="/js/lazyload.min.js"></script>
<!-- Tocbot -->
<script src="/js/tocbot.min.js"></script>
<script>
  tocbot.init({
    tocSelector: '.tocbot',
    contentSelector: '.article-entry',
    headingSelector: 'h1, h2, h3, h4, h5, h6',
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer: 'main',
    positionFixedSelector: '.tocbot',
    positionFixedClass: 'is-position-fixed',
    fixedSidebarOffset: 'auto'
  });
</script>
<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css">
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>
<script src="/dist/main.js"></script>
<!-- ImageViewer -->
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>
<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))
        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script>
<!-- MathJax -->
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
      tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
      }
  });
  MathJax.Hub.Queue(function() {
      var all = MathJax.Hub.getAllJax(), i;
      for(i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
      }
  });
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@2.7.6/unpacked/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script>
  var ayerConfig = {
    mathjax: true
  }
</script>
<!-- Katex -->
<!-- busuanzi  -->
<script src="/js/busuanzi-2.3.pure.min.js"></script>
<!-- ClickLove -->
<!-- ClickBoom1 -->
<!-- ClickBoom2 -->
<!-- CodeCopy -->
<link rel="stylesheet" href="/css/clipboard.css">
<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>
<!-- CanvasBackground -->
    <div id="music">
    <iframe frameborder="no" border="1" marginwidth="0" marginheight="0" width="200" height="52"
        src="//music.163.com/outchain/player?type=2&id=22707008&auto=0&height=32"></iframe>
</div>
<style>
    #music {
        position: fixed;
        right: 15px;
        bottom: 0;
        z-index: 998;
    }
</style>
  </div>
</body>
</html>